{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from torchvision.datasets import ImageFolder\n",
    "import torch.utils.data as Data\n",
    "import torchvision.transforms as transforms\n",
    "import  time # 导入模块\n",
    "import torch.nn as nn\n",
    "import torch\n",
    "import torch.nn.functional as F\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def corr2d(X,K):\n",
    "    \"\"\"\n",
    "\n",
    "    :param X: 输入, shape (H,w)\n",
    "    :param K: 卷积核, shape (k_h,k_w)\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    batch_size, H, W = X.shape\n",
    "    k_h, k_w = K.shape\n",
    "    # 初始化结果矩阵\n",
    "    Y = torch.zeros((batch_size, H - k_h + 1, W - k_w + 1)).to(device)\n",
    "    for i in range(Y.shape[1]):\n",
    "        for j in range(Y.shape[2]):\n",
    "            Y[:, i, j] = (X[:, i: i + k_h, j: j + k_w] * K).sum()\n",
    "    return Y\n",
    "\n",
    "def corr2d_multi_in(X,K):\n",
    "    \"\"\"\n",
    "    :param X:输入：维度(batch_size, C_in, H, W)\n",
    "    :param K: 卷积核(C_in, k_h, k_w)\n",
    "    :return: 维度(batch_size, H_out, W_out)\n",
    "    \"\"\"\n",
    "    res = corr2d(X[:,0,:,:], K[0,:,:])\n",
    "    for i in range(1, X.shape[1]):\n",
    "        # 按通道相加\n",
    "        res += corr2d(X[:,i,:,:], K[i,:,:])\n",
    "    return res\n",
    "\n",
    "def corr2d_multi_in_out(X,K):\n",
    "    \"\"\"\n",
    "    :param X: shape (batch_size, C_in, H, W)\n",
    "    :param K: shape(C_out, C_in, h, w)\n",
    "    :return: Y: shape (batch_size, C_out, H_out, W_out)\n",
    "    \"\"\"\n",
    "    return torch.stack([corr2d_multi_in(X, k) for k in K], dim = 1)\n",
    "\n",
    "class MyConv2D(nn.Module):\n",
    "    def __init__(self, in_channels, out_channels, kernel_size):\n",
    "        super(MyConv2D, self).__init__()\n",
    "        # 初始化卷积层的2个参数：卷积核、偏差\n",
    "        if isinstance(kernel_size, int):\n",
    "            kernel_size = (kernel_size, kernel_size)\n",
    "        self.weight = nn.Parameter(torch.randn((out_channels, in_channels) + kernel_size))\n",
    "        self.bias = nn.Parameter(torch.randn(out_channels, 1, 1))\n",
    "\n",
    "    def forward(self,x):\n",
    "        \"\"\"\n",
    "        x: 输出图片, 维度(batch_size,C_in, H, W)\n",
    "        \"\"\"\n",
    "        return corr2d_multi_in_out(x, self.weight) + self.bias\n",
    "\n",
    "class MyConvModule(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(MyConvModule, self).__init__()\n",
    "        # 定义三层卷积\n",
    "        self.conv = nn.Sequential(\n",
    "            MyConv2D(in_channels=3, out_channels=32, kernel_size=3),\n",
    "            nn.BatchNorm2d(32),\n",
    "            nn.ReLU(inplace=True)\n",
    "        )\n",
    "        # 输出层， 将通道数变为分类数量\n",
    "        self.fc = nn.Linear(32, num_classes)\n",
    "\n",
    "    def forward(self,X):\n",
    "        # 图片先经过三层卷积，输出维度(batch_size, C_out, H, W)\n",
    "        out = self.conv(X)\n",
    "        print(out.size())\n",
    "        # 使用平均池化层将图像的大小变为1*1\n",
    "        out = F.avg_pool2d(out, 80)\n",
    "        print(out.size())\n",
    "        out = out.squeeze()\n",
    "        out = self.fc(out)\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_epoch(net, data_loader, device):\n",
    "    net.train()\n",
    "    train_batch_num = len(data_loader)\n",
    "    total_loss = 0\n",
    "    correct = 0\n",
    "    sample_num = 0\n",
    "\n",
    "    for batch_idx, (data, target) in enumerate(data_loader):\n",
    "        print(data.size())\n",
    "        # print(target)\n",
    "        \n",
    "        data = data.to(device).float()\n",
    "        target = target.to(device).long()\n",
    "        optimizer.zero_grad()\n",
    "        output = net(data)\n",
    "        loss = criterion(output, target)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        total_loss += loss.item()\n",
    "        prediction = torch.argmax(output, 1)\n",
    "#         print(\"output\", output)\n",
    "#         print(\"prediction\", prediction)\n",
    "#         print(\"target\", target)\n",
    "        correct += (prediction == target).sum().item()\n",
    "        sample_num += len(prediction)\n",
    "    loss = total_loss / train_batch_num\n",
    "    acc = correct / sample_num\n",
    "    return loss, acc\n",
    "\n",
    "def test_epoch(net, data_loader, device):\n",
    "    net.eval()\n",
    "    test_batch_num = len(data_loader)\n",
    "    total_loss = 0\n",
    "    correct = 0\n",
    "    sample_num = 0\n",
    "    with torch.no_grad():\n",
    "        for batch_idx, (data, target) in enumerate(data_loader):\n",
    "            data = data.to(device).float()\n",
    "            target = target.to(device).long()\n",
    "            output = net(data)\n",
    "            loss = criterion(output, target)\n",
    "            total_loss += loss.item()\n",
    "            prediction = torch.argmax(output, 1)\n",
    "            correct += (prediction == target).sum().item()\n",
    "            sample_num += len(prediction)\n",
    "    loss = total_loss / test_batch_num\n",
    "    acc = correct / sample_num\n",
    "    return loss, acc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1017\n",
      "340\n",
      "torch.Size([3, 120, 85])\n",
      "{'bus': 0, 'car': 1, 'truck': 2}\n",
      "torch.Size([3, 120, 85])\n",
      "{'bus': 0, 'car': 1, 'truck': 2}\n"
     ]
    }
   ],
   "source": [
    "data_transform = transforms.Compose([\n",
    "    transforms.Resize((120,85)),\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize(mean=[0.5,0.5,0.5], std=[0.5, 0.5, 0.5])\n",
    "])\n",
    "BATCH_SIZE = 128\n",
    "train_dataset = ImageFolder(\"vehicle_dataset/train_dataset\",transform = data_transform)\n",
    "train_loader = Data.DataLoader(dataset=train_dataset, batch_size=BATCH_SIZE, shuffle=True)\n",
    "\n",
    "test_dataset = ImageFolder(\"vehicle_dataset/test_dataset\",transform = data_transform)\n",
    "test_loader = Data.DataLoader(dataset=test_dataset, batch_size=BATCH_SIZE, shuffle=True)\n",
    "# print(len(train_dataset))\n",
    "# print(len(test_dataset))\n",
    "# print(train_dataset[0][0].size())\n",
    "# print(train_dataset.class_to_idx)\n",
    "# print(test_dataset[0][0].size())\n",
    "# print(test_dataset.class_to_idx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开始训练------0-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:0\t train_loss:1.2105 \ttrain_acc: 0.2655 \ttest_loss: 0.9940 \t test_acc: 0.5735 \t training_time: 7923.42\n",
      "开始训练------1-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:1\t train_loss:1.1516 \ttrain_acc: 0.2655 \ttest_loss: 0.9943 \t test_acc: 0.5735 \t training_time: 2173.22\n",
      "开始训练------2-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:2\t train_loss:1.1030 \ttrain_acc: 0.2655 \ttest_loss: 0.9901 \t test_acc: 0.5735 \t training_time: 2175.64\n",
      "开始训练------3-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:5\t train_loss:1.0121 \ttrain_acc: 0.5742 \ttest_loss: 0.9927 \t test_acc: 0.5735 \t training_time: 2171.56\n",
      "开始训练------6-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:6\t train_loss:0.9956 \ttrain_acc: 0.5742 \ttest_loss: 1.0007 \t test_acc: 0.5735 \t training_time: 2178.40\n",
      "开始训练------7-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:7\t train_loss:0.9847 \ttrain_acc: 0.5742 \ttest_loss: 1.0163 \t test_acc: 0.5735 \t training_time: 2144.56\n",
      "开始训练------8-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:8\t train_loss:0.9749 \ttrain_acc: 0.5742 \ttest_loss: 1.0185 \t test_acc: 0.5735 \t training_time: 2176.40\n",
      "开始训练------9-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:9\t train_loss:0.9716 \ttrain_acc: 0.5742 \ttest_loss: 1.0436 \t test_acc: 0.5735 \t training_time: 2168.38\n",
      "开始训练------10-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:10\t train_loss:0.9677 \ttrain_acc: 0.5742 \ttest_loss: 1.0334 \t test_acc: 0.5735 \t training_time: 2172.19\n",
      "开始训练------11-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:11\t train_loss:0.9663 \ttrain_acc: 0.5742 \ttest_loss: 1.0461 \t test_acc: 0.5735 \t training_time: 2159.15\n",
      "开始训练------12-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([121, 3, 120, 85])\n",
      "torch.Size([121, 32, 118, 83])\n",
      "torch.Size([121, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([84, 32, 118, 83])\n",
      "torch.Size([84, 32, 1, 1])\n",
      "epoch:12\t train_loss:0.9651 \ttrain_acc: 0.5742 \ttest_loss: 1.0530 \t test_acc: 0.5735 \t training_time: 2159.08\n",
      "开始训练------13-------------\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n",
      "torch.Size([128, 3, 120, 85])\n",
      "torch.Size([128, 32, 118, 83])\n",
      "torch.Size([128, 32, 1, 1])\n"
     ]
    }
   ],
   "source": [
    "num_classes = 3\n",
    "epochs = 20\n",
    "lr = 0.001\n",
    "device = torch.device('cpu')\n",
    "# device = torch.device('cuda')\n",
    "\n",
    "net = MyConvModule().to(device)\n",
    "\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(net.parameters(), lr = lr)\n",
    "\n",
    "train_loss_list = []\n",
    "train_acc_list = []\n",
    "test_loss_list = []\n",
    "test_acc_list = []\n",
    "training_time_list = []\n",
    "for epoch in range(epochs):\n",
    "    print(\"开始训练------\" + str(epoch) + \"-------------\")\n",
    "\n",
    "    start = time.time()  #开始时间\n",
    "    train_loss, train_acc = train_epoch(net, data_loader=train_loader, device=device)\n",
    "    end = time.time()  #结束时间\n",
    "    test_loss, test_acc = 0, 0\n",
    "    test_loss, test_acc  = test_epoch(net, data_loader=test_loader, device=device)\n",
    "    train_loss_list.append(train_loss)\n",
    "    train_acc_list.append(train_acc)\n",
    "    test_loss_list.append(test_loss)\n",
    "    test_acc_list.append(test_acc)\n",
    "    training_time_list.append(end - start)\n",
    "    print(f\"epoch:{epoch}\\t train_loss:{train_loss:.4f} \\t\"\n",
    "          f\"train_acc: {train_acc:.4f} \\t\"\n",
    "          f\"test_loss: {test_loss:.4f} \\t test_acc: {test_acc:.4f} \\t training_time: {end-start:.2f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "train_loss_list = [1.2105,1.1516,1.1030,1.0121,0.9956,0.9847,0.9749,0.9716,0.9677,0.9663,0.9651]\n",
    "train_acc_list = [0.2655,0.2655,0.2655,0.5742,0.5742,0.5742,0.5742,0.5742,0.5742,0.5742,0.5742]\n",
    "test_loss_list = [0.9940, 0.9943,0.9901,0.9927,1.0007,1.0163,1.0185,1.0436,1.0334,1.0461,1.0530]\n",
    "test_acc_list = [0.5735,0.5735,0.5735,0.5735,0.5735,0.5735,0.5735,0.5735,0.5735,0.5735,0.5735,]\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "def plot(train_loss_list,label,title, subplot):\n",
    "    ax1 = plt.subplot(subplot)\n",
    "    plt.plot(list(range(len(train_loss_list))),train_loss_list, label=label)\n",
    "    ax1.set_title(title)\n",
    "    ax1.legend()\n",
    "#     plt.title(title)\n",
    "#     plt.legend()\n",
    "#     plt.show()\n",
    "plot(train_loss_list,\"train loss\",\"train loss\", 221)\n",
    "plot(test_loss_list,\"test loss\",\"test loss\", 222)\n",
    "plot(train_acc_list,\"train acc\",\"train acc\", 223)\n",
    "plot(test_acc_list,\"test acc\",\"test acc\", 224)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}